package com.flashflexpro.flexdirector.agent.view{
    import com.flashflexpro.flexdirector.agent.console.Console;

    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.geom.Point;
    import flash.utils.Timer;

    import mx.automation.Automation;
    import mx.automation.AutomationID;
    import mx.automation.IAutomationClass;
    import mx.automation.IAutomationObject;
    import mx.core.UIComponent;
    import mx.managers.SystemManager;

    public class ViewHandler{

        private static var _inst:ViewHandler;
        public static function get inst():ViewHandler{
            return _inst;
        }

        public function ViewHandler( root:SystemManager ){
            _systemManager = root;
            _esclatorTimer.addEventListener( TimerEvent.TIMER, onTimer );
            _inst = this;
        }

        private static var _systemManager:SystemManager;
        private static var _keyCode:uint;
        //Keyboard.CONTROL
        public function startLocating( keyCode:uint = 17 ):void{
            _keyCode = keyCode;
            stopListenToStage();
            _systemManager.stage.addEventListener( KeyboardEvent.KEY_DOWN, onKeyDown );
            _systemManager.stage.addEventListener( KeyboardEvent.KEY_UP, onKeyUp );
            _systemManager.addEventListener( MouseEvent.MOUSE_OVER, onMouseOver, true, 999, true );
        }

        public function stopLocating():void{
            stopListenToStage();
            clearAutoObjMark();
        }

        private function stopListenToStage():void{
            _systemManager.stage.removeEventListener( KeyboardEvent.KEY_DOWN, onKeyDown );
            _systemManager.stage.removeEventListener( KeyboardEvent.KEY_UP, onKeyUp );
            _systemManager.removeEventListener( MouseEvent.MOUSE_OVER, onMouseOver, true );
        }

        private var _keyDown:Boolean = false;
        private function onKeyDown( event:KeyboardEvent ):void{
            if( !_keyDown && event.keyCode == _keyCode ){
                _keyDown = true;
                locateCurrentAO();
            }
        }
        private function onKeyUp( event:KeyboardEvent ):void{
            if( event.keyCode == _keyCode ){
                _keyDown = false;
                clearAutoObjMark();
                Console.inst.onCheckLocated( _currentAO );
            }
        }

        private function clearAutoObjMark():void{
            if( _markCanvas != null ){
                _systemManager.stage.removeChild( _markCanvas );
                _markCanvas = null;
            }
            _esclatorTimer.stop();
        }

        private var _mouseOverTarget:UIComponent;

        private function onMouseOver( ev:MouseEvent ):void{
            var target:DisplayObject = ev.target as DisplayObject;
            while( target != null && !(target is UIComponent ) ){
                target = target.parent;
            }
            if( target == null ){
                return;
            }
            _mouseOverTarget = target as UIComponent;
            _systemManager.removeEventListener( Event.ENTER_FRAME, locateCurrentAO );
            _systemManager.addEventListener( Event.ENTER_FRAME, locateCurrentAO );
        }

        private function locateCurrentAO( e:Event = null ):void{
            _systemManager.removeEventListener( Event.ENTER_FRAME, locateCurrentAO );
            var ad:AutomationID;
            var ao:IAutomationObject = _mouseOverTarget as IAutomationObject;
            while( ao != null ){
                var ac:IAutomationClass = Automation.automationManager.automationEnvironment
                        .getAutomationClassByInstance( ao );
                if( ac != null ){
                    try{
                        if( Automation.automationManager.createIDPart( ao ) != null ){
                            ad = Automation.automationManager.createID( ao );
                            if( ad != null ){
                                var recall:IAutomationObject;
                                try{
                                    recall = Automation.automationManager.resolveIDToSingleObject( ad );
                                }
                                catch( e:Error ){
                                }
                                if( recall != null ){
                                    if( recall == ao ){
                                        break;
                                    }

                                    CONFIG::debugging{
                                        trace( this + ".locateCurrentAO: found a different ao !" );
                                    }
                                }
                            }
                            else{
                                CONFIG::debugging{
                                    trace( this + ".locateCurrentAO: createID failed:" + ao );
                                }
                            }
                        }
                        else{
                            CONFIG::debugging{
                                trace( this + ".locateCurrentAO: createIDPart failed:" + ao );
                            }
                        }
                    }
                    catch( e:Error ){
                        CONFIG::debugging{
                            trace( this + ".locateCurrentAO:" + e.getStackTrace() );
                        }
                    }
                }
                else{
                    CONFIG::debugging{
                        trace( this + ".locateCurrentAO: autoMationClass missing:" + ao );
                    }
                }
                ao = (ao as UIComponent).parent as UIComponent;
            }
            if( ao == null ){
                CONFIG::debugging{
                    trace( this + ".locateCurrentAO: _mouseOverTarget is null !" );
                }
                return;
            }
            _currentAO = ao;
            if( _keyDown ){
                clearAutoObjMark();
                markAutoObj();
            }
        }

        private static var _markCanvas:Sprite;
        private static var _esclatorTimer:Timer = new Timer( 999, 0 );

        private function markAutoObj():void{
            var d:DisplayObject = _currentAO as DisplayObject;
            var from:Point = d.localToGlobal( new Point( 0, 0 ) );
            if( _markCanvas == null ){
                _markCanvas = new Sprite();
                _systemManager.stage.addChild( _markCanvas );
            }
            if( _systemManager.stage.numChildren > 1 ){
                _systemManager.stage.setChildIndex( _markCanvas, _systemManager.stage.numChildren - 1 );
            }

            _markCanvas.graphics.clear();
            _markCanvas.graphics.lineStyle( 1, 0xFF0000 );
            _markCanvas.graphics.drawRect( from.x, from.y, d.width, d.height );

            _esclatorTimer.reset();
            _esclatorTimer.start();
        }

        private var _currentAO:IAutomationObject;

        private function onTimer( ev:TimerEvent ):void{
            if( _esclatorTimer.currentCount > 1 ){
                var aid:AutomationID = Automation.automationManager.createID( _currentAO );
                aid.removeLast();
                _currentAO = Automation.automationManager.resolveIDToSingleObject( aid );
                try{
                    markAutoObj();
                }
                catch( e:Error ){
                    CONFIG::debugging{
                        trace( this + ".onTimer:" + e.getStackTrace() );
                    }
                    clearAutoObjMark();
                }
            }
        }
    }
}